// CommandLineHelper Library
// =========================
// License: Microsoft Permissive License (Ms-PL) v1.1
// Author: Rhy Mednick (http://www.rhyverse.net)
// Project Site: http://www.codeplex.com/CommandLineHelper

using System;
using System.Collections.Generic;
using System.Text;

namespace CommandLineHelper.Attributes
{
    /// <summary>
    /// When applied to a property, this attribute instructs the command line helper parsing routine to validate 
    /// that the property value passed in is of a specified length. This can only be applied to string properties.
    /// </summary>
    [AttributeUsage(AttributeTargets.Property, Inherited = false, AllowMultiple = false)]
    public sealed class ValidateLengthAttribute : Attribute, IValidation
    {
        private int m_maxLength=int.MaxValue;
        private int m_minLength=0;
        private string m_statusMessage = String.Empty;

        /// <summary>
        /// Gets the status message that is set when the IsValid() method is called.
        /// </summary>
        public string StatusMessage
        {
            get
            {
                return m_statusMessage;
            }
        }

        /// <summary>
        /// Gets or sets the maximum allowable length of the string property that this attribute decorates.
        /// </summary>
        public int MaxLength
        {
            get { return m_maxLength; }
            set
            {
                if (value <= 0)
                {
                    throw new ArgumentOutOfRangeException("MaxLength", "MaxLength property must be greater than zero.");
                }
                if (value < this.MinLength)
                {
                    throw new ArgumentException("MaxLength property must be greater than or equal to the MinLength property.", "MaxLength");
                }
                m_maxLength = value;
            }
        }

        /// <summary>
        /// Gets or sets the minimum allowable length of the string property that this attribute decorates.
        /// </summary>
        public int MinLength
        {
            get { return m_minLength; }
            set 
            {
                if (value < 0)
                {
                    throw new ArgumentOutOfRangeException("MinLength", "MinLength property must be zero or greater.");
                }
                if (value > this.MaxLength)
                {
                    throw new ArgumentException("MinLength property must be less than or equal to the MaxLength property.", "MinLength");
                }
                m_minLength = value;
            }
        }

        /// <summary>
        /// Validates whether or not the value is within the defined size range.
        /// </summary>
        /// <param name="value">The string to validate.</param>
        /// <returns>True if the string is of the allowable size and false if it isn't.</returns>
        public bool IsValid(object value)
        {
            bool retval = true;

            //object must be string, otherwise this doesn't apply
            string strval = value as string;
            if (!string.IsNullOrEmpty(strval))
            {
                if (strval.Length < m_minLength)
                {
                    m_statusMessage = String.Format("The string '{0}' is less than the required length of {1} character(s).", strval, m_minLength);
                    retval = false;
                }
                else if (strval.Length > m_maxLength) 
                {
                    m_statusMessage = String.Format("The string '{0}' is greater than the maximum length of {1} character(s).", strval, m_maxLength);
                    retval = false;
                }
            }
            else 
            {
                m_statusMessage = "The string was null or empty so the length of it could not be evaluated.";
            }

            return retval;
        }
    }
}
